﻿using System;
using System.Web.Mvc;
using System.Web.Routing;
using Microsoft.Practices.EnterpriseLibrary.Logging;
using Microsoft.Practices.Unity;
using Microsoft.Practices.Unity.InterceptionExtension;
using Microsoft.Web.Mvc;
using Tools.Common.ServiceLocator;
using Tools.Common.UnitOfWork.Contracts;
using Tools.Configuration.Unity;
using Tools.Domain.Common.ConstraintSets;
using Tools.Domain.Common.Repositories.Contracts;
using Tools.Domain.Common.StateMachine;
using Tools.Domain.Specifications.Constraints;
using Web.App.Infrastructure.CrossCuttingConcerns.Handlers;
using Web.App.Infrastructure.Localization.Contract;
using Web.App.Infrastructure.NHibernate.Fetching;
using Web.App.Infrastructure.NHibernate.Repository;
using Web.App.Infrastructure.ObjectStore.Contracts;
using Web.App.Infrastructure.ObjectStore.Implementation;
using Web.App.Infrastructure.Security.Contracts;
using Web.App.Infrastructure.UnitOfWork.Implementations;
using Webshop20.AntiCorruptionLayers.Amazon.Services.Contracts;
using Webshop20.AntiCorruptionLayers.Lucene;
using Webshop20.Application;
using Webshop20.Application.Mappings;
using Webshop20.Application.Operations.Messages;
using Webshop20.Application.Operations.Services;
using Webshop20.Application.Queries.Services;
using Webshop20.Bindings;
using Webshop20.Domain.Catalog.Core;
using Webshop20.Domain.Catalog.Factories.Contracts;
using Webshop20.Domain.Customers.Core;
using Webshop20.Domain.Customers.Factories.Contracts;
using Webshop20.Domain.Orders.Core;
using Webshop20.Domain.Orders.Factories.Contracts;
using Webshop20.Domain.Orders.Factories.Implementation;
using Webshop20.Domain.Orders.Processes;
using Webshop20.Domain.Orders.Translations;
using Webshop20.Domain.Security.Authentication.Core;
using Webshop20.Domain.Security.Authentication.Factories.Contracts;
using Webshop20.Domain.Shared.Products.Core;
using Webshop20.Domain.Stock.Core;
using Webshop20.Domain.Stock.Services;
using Webshop20.Infrastructure.Persistence.NH.Configuration;
using Webshop20.Interface.MVC.Controllers;
using Webshop20.MVC.Helper;
using Webshop20.Presentation;

namespace Webshop20.Interface.MVC
{
    public class GlobalApplication : System.Web.HttpApplication
    {
        public static void RegisterRoutes(RouteCollection routes)
        {
            routes.IgnoreRoute("{resource}.axd/{*pathInfo}");

            routes.MapRoute(
                "Default",                                              // Route name
                "{controller}/{action}/{id}",                           // URL with parameters
                new { controller = "Home", action = "Index", id = "" }  // Parameter defaults
            );

        }

        protected void Application_Start()
        {

            ModelBinders.Binders.DefaultBinder = new Webshop20DefaultModelBinder();

            IUnityContainer unityContainer = new UnityContainer();
            var sessionFactory = NHibernateSetup.GetSessionFactory(@"Data Source=NOTEBOOK\SQLEXPRESS;Initial Catalog=webshop247;Integrated Security=True;Pooling=False");

            new MappingConfiguration();


            unityContainer = NewUnityContainer
                                .Configure()
                                .IncludeAssemblyOf<IAmazonDistributorService>()
                                .IncludeAssemblyOf<IGoodTranslator>()
                                .IncludeAssemblyOf<IGoodReservationService>()
                                .IncludeAssemblyOf<ISalesTax>()
                                .IncludeAssemblyOf<IVisitorFactory>()
                                .IncludeAssemblyOf<RegistrationController>()
                                .IncludeAssemblyOf<ILocalisationService>()
                                .IncludeAssemblyOf<IService>()
                                .IncludeAssemblyOf<Account>()
                                .IncludeAssemblyOf<Customer>()
                                .IncludeAssemblyOf<IServiceLocator>()
                                .IncludeAssemblyOf<IPresentationState>()
                                .IncludeAssemblyOf<IState>()
                                .IncludeAssemblyOf<IConstraintContext>()
                                .IncludeAssemblyOf<IIndexerFacade>()
                                .IncludeAssemblyOf<IOrderFactory>()
                                .ConfigureCtorInjectionFor<NHRepository<Good>>(new InjectionConstructor(new ResolvedParameter<IFetchingStrategyFactory>(), new ResolvedParameter<UoWWebContainer>()))
                                .ConfigureCtorInjectionFor<NHRepository<Product>>(new InjectionConstructor(new ResolvedParameter<IFetchingStrategyFactory>(), new ResolvedParameter<UoWWebContainer>()))
                                .ConfigureCtorInjectionFor<NHRepository<Visitor>>(new InjectionConstructor(new ResolvedParameter<IFetchingStrategyFactory>(), new ResolvedParameter<UoWWebContainer>()))
                                .ConfigureCtorInjectionFor<NHRepository<Account>>(new InjectionConstructor(new ResolvedParameter<IFetchingStrategyFactory>(), new ResolvedParameter<UoWWebContainer>()))
                                .ConfigureCtorInjectionFor<NHRepository<Customer>>(new InjectionConstructor(new ResolvedParameter<IFetchingStrategyFactory>(), new ResolvedParameter<UoWWebContainer>()))
                                .ConfigureCtorInjectionFor<NHRepository<ControllQuestion>>(new InjectionConstructor(new ResolvedParameter<IFetchingStrategyFactory>(), new ResolvedParameter<UoWWebContainer>()))
                                .ConfigureCtorInjectionFor<NHRepository<OrderProcess>>(new InjectionConstructor(new ResolvedParameter<IFetchingStrategyFactory>(), new ResolvedParameter<UoWWebContainer>()))
                                .ConfigureCtorInjectionFor<NHRepository<Order>>(new InjectionConstructor(new ResolvedParameter<IFetchingStrategyFactory>(), new ResolvedParameter<UoWWebContainer>()))
                                .ConfigureCtorInjectionFor<InitializeNewRegistrationService>(new InjectionConstructor(new ResolvedParameter<IAccountFactory>(), new ResolvedParameter<ICustomerFactory>(), new ResolvedParameter<NHBasedObjectStore>()))
                                .ConfigureCtorInjectionFor<SalesTax>(new InjectionConstructor(19))
                                .RegisterType<IRepository<Product>, NHRepository<Product>>()
                                .RegisterType<IRepository<Good>, NHRepository<Good>>()
                                .RegisterType<IRepository<Visitor>, NHRepository<Visitor>>()
                                .RegisterType<IRepository<Account>, NHRepository<Account>>()
                                .RegisterType<IRepository<Customer>, NHRepository<Customer>>()
                                .RegisterType<IRepository<Order>, NHRepository<Order>>()
                                .RegisterType<IRepository<OrderProcess>, NHRepository<OrderProcess>>()
                                .RegisterType<IRepository<ControllQuestion>, NHRepository<ControllQuestion>>()
                                .RegisterType<IPresentationModelFactory<RegistrationForm>, PresentationModelFactory<RegistrationForm>>()
                                .RegisterType<IUnitOfWorkRepository, StandardUoWRepository>("UoWRepository")
                                .RegisterType<IConstraintSet<Customer>, CustomerConstraintSet>(typeof(NewCustomerRegistration).Name)
                                 .RegisterType<IConstraintSet<Customer>, CustomerConstraintSet>(typeof(ExecuteAlways).Name)
                                .RegisterType<IConstraintSet<Account>, AccountConstraintSet>(typeof(ExecuteAlways).Name)
                                .RegisterType<IConstraintSet<Order>, OrderConstraintSet>(typeof(ExecuteAlways).Name)
                                .RegisterType<IConstraintSetFactory, ConstraintSetFactory>()
                                .RegisterType<IOrderFactory, OrderFactory>()
                                .RegisterType<IOrderProcessFactory, OrderProcessFactory>()
                                .RegisterType<IGoodTranslator, GoodTranslator>()
                                .RegisterType<INotificationMailTranslator, NotificationMailTranslator>()
                                .RegisterType<IObjectStoreRepository, NHBasedObjectStore>() //Standard-Auflösung -> So musss nicht jeder Konstruktor mit einem Paramater IObjectStoreRepositore explizit überschrieben werden
                //.RegisterType<IVisitorFactory, VisitorFactory>()
                                .ConfigureCtorInjectionFor<CustomerConstraintSet>(typeof(NewCustomerRegistration).Name, new InjectionConstructor(new ResolvedParameter<IConstraintContext>(typeof(NewCustomerRegistration).Name), new ResolvedParameter<IRepository<Customer>>()))
                                .ConfigureCtorInjectionFor<CustomerConstraintSet>(typeof(ExecuteAlways).Name, new InjectionConstructor(new ResolvedParameter<IConstraintContext>(typeof(ExecuteAlways).Name), new ResolvedParameter<IRepository<Customer>>()))
                                .ConfigureCtorInjectionFor<OrderConstraintSet>(typeof(ExecuteAlways).Name, new InjectionConstructor(new ResolvedParameter<IConstraintContext>(typeof(ExecuteAlways).Name)))
                                .ConfigureCtorInjectionFor<NHBasedObjectStore>(new InjectionConstructor(new ResolvedParameter<UoWWebContainer>()))
                                .ConfigureCtorInjectionFor<GetNewRegistrationDataService>(new InjectionConstructor(new ResolvedParameter<NHBasedObjectStore>()))
                                .ConfigureCtorInjectionFor<SaveNewRegistrationService>(new InjectionConstructor(new ResolvedParameter<IRepository<Account>>(), new ResolvedParameter<NHBasedObjectStore>(), new ResolvedParameter<IEncryptionService>(), new ResolvedParameter<IRepository<Customer>>(), new ResolvedParameter<IRepository<Visitor>>()))
                                .ConfigureCtorInjectionFor<NHibernateUoWFactory>(new InjectionConstructor(sessionFactory))

                                .BuildIt();

            unityContainer.RegisterType<ICallHandler, TransactionHandler>("TransactionHandler");
            unityContainer.Configure<InjectedMembers>().ConfigureInjectionFor<TransactionHandler>("TransactionHandler",
                                                                                                  new InjectionConstructor
                                                                                                    (new ResolvedParameter<UoWWebContainer>()));
            unityContainer.AddNewExtension<Interception>();
            unityContainer
                .Configure<Interception>()
                .SetInterceptorFor<IInitOrderService>(new InterfaceInterceptor())
                .SetInterceptorFor<ISaveNewRegistrationService>(new InterfaceInterceptor())
                .SetInterceptorFor<IUpdateCustomerService>(new InterfaceInterceptor())
                .SetInterceptorFor<IAddProductToCartService>(new InterfaceInterceptor())
                .SetInterceptorFor<IRemoveProductFromCartService>(new InterfaceInterceptor());




            ServiceLocator.SetServiceLocator(new UnityServiceLocator(unityContainer));

            ControllerFactory factory = new ControllerFactory(unityContainer);
            ControllerBuilder.Current.SetControllerFactory(factory);

            RegisterRoutes(RouteTable.Routes);
        }

        protected void Application_Error(object sender, EventArgs e)
        {
            Exception ex = Server.GetLastError();

            LogEntry logEntry = new LogEntry();
            logEntry.Message = string.Format("Exception Message:\n{0}\n\nInner Exception\n{1}\n\nStackTrace\n{2}\n\nTarget Site\n{3}\n\nSource\n{4}", ex.Message, ex.InnerException, ex.StackTrace, ex.TargetSite, ex.Source);
            logEntry.Categories.Add("Exceptions");
            logEntry.Severity = System.Diagnostics.TraceEventType.Warning;
            logEntry.Priority = 1;

            Logger.Write(logEntry);

        }

        protected void Session_Start(object sender, EventArgs e)
        {

        }
    }
}